package org.scboy.gateway.decorator;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;

import org.reactivestreams.Publisher;
import org.scboy.dbms.api.AreaManager;
import org.scboy.dbms.api.DictionaryManager;
import org.scboy.gateway.entity.AreaType;
import org.scboy.gateway.entity.ConvertType;
import org.scboy.gateway.entity.DateType;
import org.scboy.gateway.entity.DicType;
import org.scboy.gateway.entity.OrgType;
import org.scboy.gateway.enums.AreaConvertType;
import org.scboy.gateway.enums.OrgConvertType;
import org.scboy.rbac.api.OrgManager;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
import java.util.Date;

/**
 * 
 * 数据格式转换
 * @author 杨浩
 */
public class ConvertDecorator extends ServerHttpResponseDecorator{
	
	private OrgManager org;

	private AreaManager area;

	private DictionaryManager dic;
	
	private ServerHttpRequest request;
	
	/**
	 * 转换配置信息
	 */
	private ConvertType type;
	
	public ConvertDecorator(OrgManager org,AreaManager area,DictionaryManager dic,ServerHttpRequest request, ServerHttpResponse delegate){
		super(delegate);
		this.request=request;
		this.org=org;
		this.area=area;
		this.dic=dic;
	}

	@Override
	@SuppressWarnings(value = "unchecked")
	public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
		if(body instanceof Flux) {
			Flux<DataBuffer> fluxBody = (Flux<DataBuffer>) body;

			return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
				DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
				DataBuffer join = dataBufferFactory.join(dataBuffers);

				byte[] content = new byte[join.readableByteCount()];
				join.read(content);
				DataBufferUtils.release(join);//释放掉内存
				
				String bodyStr = new String(content, Charset.forName("UTF-8"));

                //修改响应体
				bodyStr = modifyBody(bodyStr);

				getDelegate().getHeaders().setContentLength(bodyStr.getBytes().length);
				return bufferFactory().wrap(bodyStr.getBytes());
			}));
		}
		return super.writeWith(body);
	}
	
	/**
	 * 重写参数
	 * @param jsonStr
	 * @return
	 */
	private String modifyBody(String jsonStr){
		
		//获取转换配置
		String convertStr=request.getHeaders().getFirst("Bmps-Convert-Config");
		type=new JSONObject(Base64.decodeStr(convertStr)).toBean(ConvertType.class);
		JSONObject json = new JSONObject(jsonStr);
		if(json.getBool("success")) {
			Object data= json.get("data");
			
			if(data instanceof JSONArray) {
				JSONArray array=(JSONArray)data;
				array.forEach((obj)->{
					JSONObject model=(JSONObject)obj;
					dataConvert(model);
				});
			}else if(data instanceof JSONObject) {
				JSONObject model=(JSONObject)data;
				dataConvert(model);
			}
		}
		
		return json.toString();
	}
	
	/**
	 * 数据转换
	 * @param data
	 */
	private void dataConvert(JSONObject data) {
		
		//转换地区
		if(type.getAreaConvert()!=null) {
			for (AreaType type : type.getAreaConvert()) {
				String value=data.getStr(type.getName());
				if(StrUtil.isNotEmpty(value)) {
					String address="";
					if(type.getType()==AreaConvertType.NAME) {
						address=area.getName(value);
					}else {
						address=area.getAddress(value);
					}
					if(StrUtil.isEmpty(type.getRename())) {
						data.set(type.getName(), address);
					}else {
						data.set(type.getRename(), address);
					}
				}
			}
		}
		
		//时间格式转换
		if(type.getDateFormat()!=null) {
			for (DateType type : type.getDateFormat()) {
				Date date=data.getDate(type.getName());
				if(date!=null) {
					if(StrUtil.isEmpty(type.getRename())) {
						data.set(type.getName(), DateUtil.format(date, type.getFormat()));
					}else {
						data.set(type.getRename(), DateUtil.format(date, type.getFormat()));
					}
				}
			}
		}
		
		//组织转换
		if(type.getOrgConvert()!=null) {
			for (OrgType type : type.getOrgConvert()) {
				String value=data.getStr(type.getName());
				if(StrUtil.isNotEmpty(value)) {
					String orgName="";
					if(type.getType()==OrgConvertType.ORG_NAME) {
						orgName=org.getOrgName(value);
					}else if(type.getType()==OrgConvertType.ORG_LOCATION){
						orgName=org.getOrgLocation(value);
					}else {
						orgName=org.getOrgShortName(value);
					}
					if(StrUtil.isEmpty(type.getRename())) {
						data.set(type.getName(), orgName);
					}else {
						data.set(type.getRename(), orgName);
					}
				}
			}
		}
		
		//字典转换
		if(type.getDicConvert()!=null) {
			DicType [] config=type.getDicConvert();
			for (DicType dicType : config) {
				String value=data.getStr(dicType.getName());
				if(StrUtil.isNotEmpty(value)) {
					if(StrUtil.isEmpty(dicType.getRename())) {
						data.set(dicType.getName(), dic.getName(value));
					}else {
						data.set(dicType.getRename(), dic.getName(value));
					}
				}
			}
		}
	}
}